`timescale 1ns / 1ns

module img_block #(
    parameter [15:0] STEP_X = 16'd8,
    parameter [15:0] STEP_Y = 16'd8
)
(
    input rst,
    input clk,
    input signed [15:0] xst, yst,
    input signed [15:0] x[2:0],
    input signed [15:0] y[2:0],
    input [15:0] z[2:0],
	input boot,
    output busy
);

reg [63:0] prog[255:0];
reg [7:0] pc, pcend;

wire [63:0] ins;
wire [7:0][7:0] mask;

wire [7:0][7:0][23:0] pixels;

assign ins = prog[pc];

genvar i, j;

// SIMT
generate
    for (i = 0; i < STEP_X; i = i + 1) begin : coreX
        for (j = 0; j < STEP_Y; j = j + 1) begin : coreY
            img_core core_inst(
                .rst(rst),
                .clk(clk),
                .ins(ins),
                .xpos(xst + i[15:0]), .ypos(yst + j[15:0]),
                .x(x), .y(y),
                .busy(busy),
                .mask(mask[i][j]),
                .pixel(pixels[i][j])
            );
        end
    end
endgenerate

localparam [1:0] STATE_IDLE = 2'b00,
                 STATE_BOOT = 2'b01,
                 STATE_RUN = 2'b10,
                 STATE_WRITE = 2'b11;
reg [1:0] state;

assign busy = (state != STATE_IDLE);

wire wr = (state == STATE_WRITE);

img_frame frame(
    .clk(clk),
    .wr(wr),
    .x(xst[10:3]), .y(yst[10:3]),
    .data(pixels)
);

always @(posedge clk or negedge rst) begin
    if (!rst) begin
        state <= STATE_IDLE;
    end
    else begin
        case (state)
            STATE_IDLE: begin
                if (boot) begin
                    pc <= 0;
                    state <= STATE_BOOT;
                    // 测试
                    pcend <= 3;
                    // sub r1,r1.xyzw,r0.xyzw
                    prog[0] <= 64'h000006C006C10102;
                    // mul r0,r0.xyzw,r1.xyzw
                    prog[1] <= 64'h000006C106C00003;
                    // nop r1,r0.xyzw,r1.xyzw
                    prog[2] <= 64'h000006C106C00100;
                    // nop
                    prog[3] <= 64'h0000000000000000;
                end
            end
            STATE_BOOT: begin
                state <= STATE_RUN;
            end
            STATE_RUN: begin
                if (pc == pcend) begin
                    state <= STATE_WRITE;
                end
                else begin
                    pc <= pc + 1;
                end
            end
            STATE_WRITE: begin
                state <= STATE_IDLE;
            end
        endcase
    end
end

endmodule